home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: MegaDisc / MegaDisc 06 (1988)(MegaDisc Digital Publishing)(AU)[m][WB].zip / MegaDisc 06 (1988)(MegaDisc Digital Publishing)(AU)[m][WB].adf / PROGRAMS / AboutAbort < prev    next >
Text File  |  1988-03-28  |  16KB  |  254 lines

  1.  
  2.                                ABORTCOMMAND
  3.                                ~~~~~~~~~~~~
  4.                   written by Ken J. White (7th March 1988)
  5.  
  6.       [ED. NOTE: This useful utility is a welcome addition to the system of
  7.       anyone fed up with those pesky software errors. Ken has also included
  8.       the source code with his contribution, and in this description gives
  9.       a very lucid explanation of how he programmed in MC68000 Assembly
  10.       Language. Necessary reading for would-be programmers. Ken might
  11.       provide us with another couple of useful commands for the next
  12.       issue, including an intelligent ASK command which will continue
  13.       processing a batch file after a specified period.]
  14.  
  15.    ************************************************************************
  16.  
  17.          This is a handy little utility for anyone who is developing
  18.       software for the Amiga. It also has uses for those not inclined
  19.       to writing software. A quite common occurrence for those testing
  20.       programs is that the program finds itself in an endless loop,
  21.       never returning control back to the user. For a multitasking
  22.       computer such as the Amiga, all you have to do is write that
  23.       task off and continue in some other task that you started up
  24.       previously. The problem is that the misguided task will probably
  25.       be consuming a large proportion of the microprocessor time slices,
  26.       thus slowing everything else down (as if you had plenty of time
  27.       waste). Rather than reboot, you can now use ABORTCOMMAND to regain
  28.       control of a CLI task that is locked up by a faulty command. It
  29.       also can be used in cases where a command has produced THAT well
  30.       known requester (you know the one...... Software Error. Task
  31.       held...... etc)! In that case you get the task back! The requestor
  32.       remains, but is totally inactive, thus preventing that annoying
  33.       behaviour of the system ominously replacing it at the front in the
  34.       top left-hand corner every time you put a disk in a drive.
  35.  
  36.          There are, however, limitations on the use of ABORTCOMMAND.
  37.       First, there must be either Workbench or another CLI active in
  38.       order to use ABORTCOMMAND. Thus it is common sense to have at
  39.       least two processes (Workbench and/or CLIs) active before any
  40.       programs are tested. ABORTCOMMAND can be accessed from either
  41.       a CLI or Workbench. Second, ABORTCOMMAND can be used to abort
  42.       CLI commands ONLY. It cannot be used to abort Workbench programs,
  43.       tasks in general, or interrupts. To abort these would require
  44.       information that is not readily available to the user. This is
  45.       especially true with Workbench programs. Third, ABORTCOMMAND
  46.       can only be used where multitasking and interrupts have not
  47.       been disabled by the faulty command or where a guru has not been
  48.       generated. More general, ABORTCOMMAND cannot be used when the
  49.       whole system has frozen, crashed, or died some other horrible
  50.       death. Fourth, ABORTCOMMAND does not perform any clean-up
  51.       operations except for what DOS normally does when a command
  52.       exits. Any memory, signals, traps, etc, that the command has
  53.       allocated will remain allocated. Any files, devices, windows,
  54.       libraries, etc, that the command opens will remain open. Any
  55.       tasks, processes, interrupts, etc, that have the command has
  56.       created, unless they can remove themselves, will remain. An
  57.       example was given above where an inactive requester remains.
  58.       Finally, the use of ABORTCOMMAND should NEVER be regarded as
  59.       completely safe. It will generally be operating in an unknown
  60.       environment where the effects of aborting a command is quite
  61.       unpredictable. Fortunately, most critical operations will be
  62.       performed with multitasking disabled, so that you will be
  63.       protected from the worst effects of unpredictability.
  64.  
  65.          The use of ABORTCOMMAND is quite straightforward. Simply
  66.       type it as a CLI command or double-click it's icon. A window
  67.       will open and you will be asked to input the CLI number of the
  68.       command to abort. For commands initiated by RUN, this is the
  69.       CLI number generated by RUN, not of the CLI in which RUN was
  70.       performed. The name of the command will be printed and you will
  71.       be asked whether you wish to abort it. Type "y","Y","yes", or
  72.       in fact anything that starts with a "y" or "Y", and the named
  73.       command will be aborted unless some problem is found. The program
  74.       will then exit. If the CLI number input was found to be invalid,
  75.       or you typed something that didn't start with "y" or "Y" when
  76.       asked whether to abort, or some other problem was encountered, you
  77.       will be asked if you wish to exit. Again "y","Y" as the first
  78.       character will cause the program to exit, otherwise it will
  79.       restart by asking you to input a CLI number. On exit, regardless
  80.       of whether a command was aborted or not, the window will be closed
  81.       and the return code will be zero (no error). Errors that prevent
  82.       the window from being opened will generate a return code of 20
  83.       (fail). The aborted command will generate a return code of 100 but
  84.       no message.
  85.  
  86.  
  87.  
  88.                           Technical Information
  89.                           ~~~~~~~~~~~~~~~~~~~~~
  90.  
  91.          This section is to give programmers and hackers in general more
  92.       information on how this utility operates and give a little insight
  93.       on other possible uses. Because these other uses are not currently
  94.       implemented, I have supplied the source code (MC68000 Assembly
  95.       Language) so that modifications may be made. An attempt was made
  96.       to make this code flexible so that modifications will not be too
  97.       difficult. The code has not been liberally interspersed with
  98.       comments, however, I believe that I have supplied sufficient
  99.       information to allow anyone who knows what they are doing to
  100.       easily understand and modify the code.
  101.  
  102.          The code consists of four sections: AbortCommand, function,
  103.       subroutines, and donated_segment.
  104.  
  105.          "AbortCommand" performs the initialisation procedure. This
  106.       consists of allocating and clearing 320 bytes of stack space,
  107.       obtaining the address of our task, then testing whether we are
  108.       running under Workbench or a CLI. If under Workbench, we wait for,
  109.       then obtain the message that Workbench has sent us. The address of
  110.       the predecessor segment to donated_segment is obtained using the
  111.       label, external_code, to identify the segment, donated_segment.
  112.       (This will be explained in greater detail below.). The DOS library
  113.       is then opened and if under CLI, the default output file handle is
  114.       obtained (for error messages). The CON: window is then opened.
  115.       Subroutine, function, (fully explained below) is performed.
  116.       "AbortCommand" also performs the finalisation procedure of closing
  117.       the window, closing the DOS library, and if run from Workbench,
  118.       replying to its message. Stack space is deallocated then we RTS
  119.       back to DOS. Open library and window errors are also handled.
  120.  
  121.          "function" performs the real magic. First, it clears D7, which
  122.       is used internally, as a set of flags. Then, it asks for the CLI
  123.       number of the command to abort. All message output (except the
  124.       command name string) is handled the same way. The subroutine,
  125.       output_string, uses a message base address (in A0) and a message
  126.       number (in D0) to output a variable length null-terminated string
  127.       to the file handler (in D1) (the window). The message base address
  128.       corresponds to the start of the first message which is message
  129.       number 1. The subroutine, input_cli_num, inputs a decimal or
  130.       hexadecimal number of up to 8 digits. The use of the "$" character
  131.       immediately before the number (ie, no spaces) distinguishes a
  132.       hexadecimal from a decimal number. This allows the subroutine to
  133.       be used for inputing such data as task addresses, etc. The
  134.       subroutine converts the ASCII string to a binary value and returns
  135.       the result (or zero if invalid) in D0. "function" then disables
  136.       interrupts then tests the existance of the requested CLI. If it
  137.       exists, the task address of the CLI is determined and placed in
  138.       A1. This is compared with our task address. If different, the
  139.       Ready and Wait task lists are scanned in search of the task. If
  140.       not found, bit 30 of D7 will be set. If found in the Wait list,
  141.       bit 31 of D7 will be set (although this is not subsequently used).
  142.       Subroutine, command_name, is then performed. This routine tests
  143.       whether a command is currently loaded, if so, it copies the name
  144.       string to our input buffer, interrupts are enabled and the copied
  145.       name string is outputed. Otherwise, bit 29 of D7 is set, then
  146.       interrupts are enabled. "function" then asks whether you wish to
  147.       abort the command. (The function of subroutine, confirm_abort, was
  148.       adequately explained above.). Interrupts are then disabled.
  149.       Because of the period of enabled interrupts (and therefore,
  150.       multitasking) we cannot trust any of the information obtained
  151.       earlier. The CLI number is used to redetermine the task address
  152.       which is verified with the previously determined task address.
  153.       If it verifies as the same, the Ready and Wait task lists are
  154.       rescanned. If the task is not found, the state of bit 30 of D7 is
  155.       reversed. I try to take into consideration all possibilities,
  156.       including that of the task inadvertently removing itself from the
  157.       task lists. However, because the environment is unknown, we must
  158.       view tasks, that are not in the lists, with suspicion. The point
  159.       is that we base our decision of whether or not to abort it on the
  160.       result of both task list scans. A change, especially where the
  161.       task has moved back into the lists, suggests that the task may be
  162.       under external control and best left alone. Bit 30 of D7 is
  163.       tested. If 0, we assume the task has not moved (we fully expect
  164.       the task to interchange between Ready, Run, and Wait states and
  165.       thus ignore such changes except that bit 31 of D7 correctly
  166.       reflects the state), and if the task is not in the lists, we set
  167.       bit 30 of D7. "function" then obtains the address of the tail
  168.       segment of the command to abort, the stack pointer to the DOS
  169.       supplied return address, and the stack pointer to the task's
  170.       stored stack frame. In each case, a test is made to assure that
  171.       the command has not exited or is not in the process of exiting.
  172.       The address associated with the label, external_pc_cli, is
  173.       obtained and stored for later use. This address is, eventually,
  174.       to become the command's new program counter. Note that the
  175.       label corresponds to the same address as label, external_code.
  176.       However, I chose to use different labels for greater flexibility
  177.       in case modifications are made. The segment, donated_segment, is
  178.       then removed from our code's segment list and added to the tail
  179.       of the segment list of the command to abort. (An explanation of
  180.       why this is done is best deferred till later.). All the command
  181.       task's registers are transferred from the stored stack frame to
  182.       a data storage area within segment, donated_segment, then the
  183.       stored program counter is replaced and the stored status
  184.       register is cleared. The new stack pointer, which points to the
  185.       DOS supplied return address, is not stored within the task's
  186.       context but, rather, within the segment, donated_segment. This
  187.       was done to maintain flexibility should this code every be
  188.       modified. Finally the task is transferred to the TaskReady list
  189.       then the interrupts are enabled. The next time the task regains
  190.       the microprocessor, it will exit back to DOS. If any problems
  191.       were encountered along the way you will be asked if you wish to
  192.       exit. The subroutine, confirm_exit, is essentially the same as
  193.       subroutine, confirm_abort, except that a different message is
  194.       generated. "function" will either exit or restart from label,
  195.       function.
  196.  
  197.          "subroutines" contain all the miscellaneous subroutines used
  198.       by our code. I believe an adequate description has been given.
  199.       If you wish to find out more, you will have to look at the code
  200.       itself.
  201.  
  202.          "donated_segment" is the segment that is transferred to the
  203.       command's segment list. It contains the code to allow the
  204.       command to exit back to DOS. It also contains all of the task's
  205.       original registers and the task's new stack pointer. The task's
  206.       new stack pointer is utilised by the code so that at the entry
  207.       point, the entire task context is available, which it would not
  208.       have been if the stack pointer were altered by "function".
  209.       Because the command is aborted by altering the task's program
  210.       counter and allowing multitasking to take its course, thereby
  211.       forcing it to exiting via external_pc_cli, which is part of our
  212.       context, I had to consider the possibility of our program
  213.       exiting before the command to abort regains the microprocessor.
  214.       This would cause the program counter to point to invalid code,
  215.       resulting in a system crash. I decided to remove the segment,
  216.       "donated_segment", from our context and add it the context of
  217.       the command. By disowning the segment, our code can exit at any
  218.       time with a clear conscience. When the aborted command exits,
  219.       DOS will free the memory associated with the segment as if it
  220.       were originally loaded as part of the command.
  221.  
  222.          Although it is possible to modify the code so that it will
  223.       abort Workbench objects, tasks in general, interrupt handlers
  224.       and servers, etc, one application that I find tantalizing is to
  225.       investigate locked up commands "on the fly", ie, while it is
  226.       actually running. By modifying ABORTCOMMAND and using your
  227.       favourite debugger as if you are debugging your modified
  228.       ABORTCOMMAND, you can invesigate the state of the locked up
  229.       command at some instant during its execution, perhaps following
  230.       its progress in nearly real time (I can't say what can actually
  231.       be done since I don't know the nature of your debugger). By
  232.       setting up break-points within your modified ABORTCOMMAND, you
  233.       can look at the stored registers within segment, donated_segment,
  234.       to see exactly what is happening. In such a case it may be
  235.       desirable to assemble section, donated_segment, separately
  236.       using the symbol dump option (this is why each register storage
  237.       location has its own label even though the labels are not
  238.       referenced at all by my code). A more sophisticated way would
  239.       be to modify ABORTCOMMAND so that it lists all the register
  240.       values to a window. To modify ABORTCOMMAND to perform debugging
  241.       operations, do not allow the code to transfer "donated_segment"
  242.       or modify the task's stored stack frame. Also, remember that
  243.       interrupts are disabled throughout most of the code's operation,
  244.       so you will be well advised to enable interrupts before doing
  245.       anything that requires multitasking. I hope you find this
  246.       information useful and that you enjoy using ABORTCOMMAND.
  247.  
  248.                                                    Ken White
  249.                                                    ~~~~~~~~~
  250.  
  251.                                  THE END
  252.                                  ~~~~~~~
  253.  
  254.